#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>

//生产者消费者模型
//生产者和生产者之间为互斥关系
//消费者和消费者之间为互斥关系
//生产者和消费者之间为同步互斥关系

pthread_mutex_t mutex;//互斥量
pthread_mutex_t mutex_con;
pthread_cond_t p_cond;
int count=0;


//1.实现交易场所（带头结点，不带环的单向链表(栈结构)）
typedef struct Node
{
  struct Node *_next;
  int data;
}Node;

void ListInit(Node *Head) 
{
  Head=(Node *) malloc(sizeof(Node));
  Head->_next=NULL;
}

Node Head;

void ListPushFront(Node * Head,int val)
{
  if(Head==NULL)
  {
    return;
  }
  Node * new_node=(Node *)malloc(sizeof(Node));
  new_node->data=val;
  new_node->_next=Head->_next;
  Head->_next=new_node;
}

void ListPopFront(Node * Head,int * val)
{
  if(Head==NULL)
  {
    return;
  }
  if(Head->_next==NULL)
  {
    return;
  }
  Node * to_delete=Head->_next;
  *val=to_delete->data;
  Head->_next=to_delete->_next;
  free(to_delete);
}

void ListDestroy(Node *Head)
{
  if(Head==NULL||Head->_next==NULL)
  {
    return;
  }
  Node * cur=Head->_next;
  while(cur!=NULL)
  {
    Node * to_delete=cur;
    cur=cur->_next;
    free(to_delete);
  }
}

//2.**********************实现三种关系*****************************
//*******生产者****************
void * Producer(void * arg){

  (void) arg;
  while(1)
  {
    while(1)
    {
      pthread_mutex_lock(&mutex);//在进行生产之前先获取锁(控制互斥关系)
      ListPushFront(&Head,++count);
      printf("生产：%d\n",count);
      pthread_cond_signal(&p_cond);//在生产之后进行信号量加一操作，通知消费者可以进行消费了
      pthread_mutex_unlock(&mutex);//在生产之后释放锁
      usleep(187761);
    }
  }
  return NULL;
}

//*******消费者****************
void * Consumer(void * arg){

  (void) arg;
  while(1)
  {
    pthread_mutex_lock(&mutex);//在进行消费之前先获取锁
    int tmp=-1;
    while(Head._next==NULL)//当没有节点时，进行循环等待
    {
      pthread_cond_wait(&p_cond,&mutex);//循环等待生产者进行生产,条件变量
    }
    ListPopFront(&Head,&tmp);
    if(tmp==-1){
      //说明没有进行消费
      break;
    }
    printf("消费：%d\n",tmp);
    pthread_mutex_unlock(&mutex);//消费完后释放锁
    usleep(4551);
  }
  return NULL;
}


//2.*********************实现两种角色*****************************
void test()
{
  const int N=6;
  pthread_t thread[N];
  int i=0;
  ListInit(&Head);
  pthread_mutex_init(&mutex,NULL);
  pthread_cond_init(&p_cond,NULL);
  //创建几个生产者
  for(i=0;i<N/2;i++)
  {
    pthread_create(&thread[i],NULL,Producer,NULL);
  }
  //创建几个消费者
  for(i=0;i<N-N/2;i++)
  {
    pthread_create(&thread[i],NULL,Consumer,NULL);
  }

  for(i=0;i<N;++i)
  {
    pthread_join(thread[i],NULL);
  }

  pthread_mutex_destroy(&mutex);
  pthread_cond_destroy(&p_cond);
}

int main()
{
  test();
  return 0;
}
